package com.seanzx.constant;

import com.seanzx.lexical.TokenType;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class SymbolTable {
    private static final Map<String, TokenType> TABLE = new HashMap<>();

    public static final String SELECT = "SELECT";
    public static final String INSERT = "INSERT";
    public static final String CREATE = "CREATE";
    public static final String UPDATE = "UPDATE";
    public static final String DELETE = "DELETE";
    public static final String USE = "USE";
    public static final String SHOW = "SHOW";
    public static final String ALTER = "ALTER";
    public static final String DROP = "DROP";
    public static final String MODIFY = "MODIFY";
    public static final String ADD = "ADD";
    public static final String SET = "SET";
    public static final String GET = "GET";

    static {
        TABLE.put(SET, TokenType.ACTION);
        TABLE.put(GET, TokenType.ACTION);
        TABLE.put(SELECT, TokenType.ACTION);
        TABLE.put(INSERT, TokenType.ACTION);
        TABLE.put(CREATE, TokenType.ACTION);
        TABLE.put(UPDATE, TokenType.ACTION);
        TABLE.put(DELETE, TokenType.ACTION);
        TABLE.put(USE, TokenType.ACTION);
        TABLE.put(SHOW, TokenType.ACTION);
        TABLE.put(ALTER, TokenType.ACTION);
        TABLE.put(DROP, TokenType.ACTION);
        TABLE.put(MODIFY, TokenType.ACTION);
        TABLE.put(ADD, TokenType.ACTION);
        TABLE.put("VARIABLES", TokenType.OBJECT);
        TABLE.put("TABLE", TokenType.OBJECT);
        TABLE.put("DATABASE", TokenType.OBJECT);
        TABLE.put("DATABASES", TokenType.OBJECT);
        TABLE.put("INDEX", TokenType.OBJECT);
        TABLE.put("KEY", TokenType.OBJECT);
        TABLE.put("PRIMARY", TokenType.OBJECT);
        TABLE.put("INTO", TokenType.OPERATOR_EN);
        TABLE.put("FROM", TokenType.OPERATOR_EN);
        TABLE.put("VALUES", TokenType.OPERATOR_EN);
        TABLE.put("WHERE", TokenType.OPERATOR_EN);
        TABLE.put("ALL", TokenType.OPERATOR_EN);
        TABLE.put("LEFT", TokenType.OPERATOR_EN);
        TABLE.put("RIGHT", TokenType.OPERATOR_EN);
        TABLE.put("FULL", TokenType.OPERATOR_EN);
        TABLE.put("INNER", TokenType.OPERATOR_EN);
        TABLE.put("OUTER", TokenType.OPERATOR_EN);
        TABLE.put("UNION", TokenType.OPERATOR_EN);
        TABLE.put("JOIN", TokenType.OPERATOR_EN);
        TABLE.put("IN", TokenType.OPERATOR_EN);
        TABLE.put("EXISTS", TokenType.OPERATOR_EN);
        TABLE.put("NOT", TokenType.OPERATOR_EN);
        TABLE.put("LIKE", TokenType.OPERATOR_EN);
        TABLE.put(">", TokenType.OPERATOR);
        TABLE.put(">=", TokenType.OPERATOR);
        TABLE.put("<", TokenType.OPERATOR);
        TABLE.put("<=", TokenType.OPERATOR);
        TABLE.put("=", TokenType.OPERATOR);
        TABLE.put("!=", TokenType.OPERATOR);
        TABLE.put("<>", TokenType.OPERATOR);
        TABLE.put(".", TokenType.OPERATOR);
        TABLE.put("(", TokenType.OPERATOR);
        TABLE.put(")", TokenType.OPERATOR);
        TABLE.put(",", TokenType.OPERATOR);
        TABLE.put("*", TokenType.OPERATOR);
    }

    public static TokenType get(String value) {
        return TABLE.getOrDefault(value, TokenType.VALUE);
    }

    public static String[] operators() {
        List<String> operators = TABLE.entrySet().stream()
                .filter(entry -> entry.getValue().equals(TokenType.OPERATOR))
                .map(Map.Entry::getKey)
                .sorted((e1, e2) -> {
                    if (e1.length() != e2.length()) {
                        return e1.length() - e2.length();
                    }
                    return e1.compareTo(e2);
                })
                .collect(Collectors.toList());
        String[] results = new String[operators.size()];
        for (int i = 0; i < operators.size(); i++) {
            results[i] = operators.get(i);
        }
        return results;
    }

}
